#include <iostream>
#include <fstream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

#define MULTICAST_GROUP "224.0.0.1"
#define PORT 8888
#define BLOCK_SIZE 1400

struct FileHeader {
    uint32_t fileSize;
    char filename[256];
};

int main() {
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("socket");
        return 1;
    }

    struct sockaddr_in localAddr;
    memset(&localAddr, 0, sizeof(localAddr));
    localAddr.sin_family = AF_INET;
    localAddr.sin_addr.s_addr = INADDR_ANY;
    localAddr.sin_port = htons(PORT);

    if (bind(sock, (struct sockaddr*)&localAddr, sizeof(localAddr)) < 0) {
        perror("bind");
        close(sock);
        return 1;
    }

    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP);
    mreq.imr_interface.s_addr = INADDR_ANY;
    if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        perror("setsockopt IP_ADD_MEMBERSHIP");
        close(sock);
        return 1;
    }

    FileHeader header;
    struct sockaddr_in senderAddr;
    socklen_t senderAddrLen = sizeof(senderAddr);
    if (recvfrom(sock, &header, sizeof(header), 0, (struct sockaddr*)&senderAddr, &senderAddrLen) != sizeof(header)) {
        std::cerr << "Failed to receive header" << std::endl;
        close(sock);
        return 1;
    }

    header.fileSize = ntohl(header.fileSize);
    std::ofstream file(header.filename, std::ios::binary);
    if (!file) {
        std::cerr << "Failed to create file: " << header.filename << std::endl;
        close(sock);
        return 1;
    }

    uint32_t totalReceived = 0;
    char buffer[BLOCK_SIZE];
    while (totalReceived < header.fileSize) {
        ssize_t bytesRecv = recvfrom(sock, buffer, BLOCK_SIZE, 0, (struct sockaddr*)&senderAddr, &senderAddrLen);
        if (bytesRecv < 0) {
            perror("recvfrom");
            break;
        }
        file.write(buffer, bytesRecv);
        totalReceived += bytesRecv;
        std::cout << "Received " << totalReceived << " of " << header.fileSize << " bytes" << std::endl;
    }

    file.close();
    close(sock);

    if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        perror("setsockopt IP_DROP_MEMBERSHIP");
    }

    return 0;
}#define _CRT_SECURE_NO_WARNINGS